<?php
/**
 * This is the file to control page processing.
 * 
 * @author	Justin Yoo
 * @version	0.0.1.0001
 * @package	KYR.Core
 * 
 */

//	Checks if this file is called within the framework; otherwise terminates.
if (!defined("IS_FRAMEWORK") || !IS_FRAMEWORK)	header("Location: http://".$_SERVER["HTTP_HOST"]."/error/404");

//	Imports relevant files.
require_once CORE_PATH."KYR.Core.Debug.php";
require_once CORE_PATH."KYR.Core.Request.php";
require_once CORE_PATH."KYR.Core.Database.php";

/**
 * This is class Controller that control every page process.
 * 
 * Processes from page request via load modules and widgets to render templates.
 * 
 * @author	Justin Yoo
 * @package	KYR.Core
 *
 */
class Controller extends BaseObject
{
	/**
	 * Initiates the Controller class.
	 *
	 * @access	public
	 *
	 */
	public function __construct()
	{
		$this->request		= new Request();
		$this->variables	= array();
	}
	
	/**
	 * Processes the page request.
	 *
	 * @access		public
	 * @exception	Exception
	 *
	 */
	public function ProcessRequest()
	{
		try
		{
			//	Checks whether the page requested exists or not.
			$this->request->CheckUri();
			if ($this->request->existUri)
			{
				//	Processes the error page if the URL contains "error".
				if (strtolower(substr($this->request->uri, 0, strpos($this->request->uri, "/"))) == "error")
				{
					$moduleName	= "Content";
					require_once MODULE_PATH."KYR.Modules.".$moduleName.".php";
					$statusCode	= substr($this->request->uri, strpos($this->request->uri, "/") + 1);
					$module = new $moduleName($this->request, $statusCode);
					switch ($statusCode)
					{
						case 404:
							$module->error	= new Exception($statusCode." - Page not found");
							break;
						case 500:
							$module->error	= new Exception($statusCode." - Internal server error");
							break;
						case 503:
							$module->error	= new Exception($statusCode." - Connection refused");
							break;
					}
					$modules[$moduleName]	= $module;
					$this->_LoadLayout($modules, null);
				}
				else
				{
					//	Checks if the URI is aliased or not
					if ($this->request->isAlias)
					{
						//	Redirects the page to the original page.
						header("Location: ".BASE_URL.$this->request->aliasedUri);
					}
					else
					{
						//	Loads modules corresponding to the page.
						$modules = $this->_LoadModules();
						//	Loads widgets corresponding to the page.
						$widgets = $this->_LoadWidgets();
						//	Loads the layout for the page.
						$this->_LoadLayout($modules, $widgets);
					}
				}
			}
			else
			{
				$moduleName	= "Content";
				require_once MODULE_PATH."KYR.Modules.".$moduleName.".php";
				$module = new $moduleName($this->request, 404);
				$module->error			= new Exception("404 - Page not found");
				$modules[$moduleName]	= $module;
				$this->_LoadLayout($modules, null);
			}
		}
		catch (Exception $ex)
		{
			$moduleName = "Content";
			require_once MODULE_PATH."KYR.Modules.".$moduleName.".php";
			$module = new $moduleName($this->request, 500);
			$module->error			= $ex;
			$modules[$moduleName]	= $module;
			$this->_LoadLayout($modules, null);
		}
	}
	
	/**
	 * Loads modules corresponding to the page.
	 *
	 * @access	private
	 * @return	array	Returns the list of modules.
	 *
	 */
	private function _LoadModules()
	{
		$modules	= array();
		try
		{
			$moduleNames	= $this->GetObjectNames_("module");
			if (isset($moduleNames) && count($moduleNames) > 0)
			{
				foreach ($moduleNames as $moduleName)
				{
					$filename = MODULE_PATH."KYR.Modules.".$moduleName["module"].".php";
					if (file_exists($filename))
						require_once $filename;
					else
						throw new Exception("Module not found");
					
					$module = new $moduleName["module"]($this->request);
					$modules[$moduleName["module"]] = $module;
				}
			}
			else
				throw new Exception("Module not found");
		}
		catch (Exception $ex) { throw $ex; }
		return $modules;
	}
	
	/**
	 * Loads widgets corresponding to the page.
	 *
	 * @access	private
	 * @return	array	Returns the list of widgets.
	 *
	 */
	private function _LoadWidgets()
	{
		$widgets	= array();
		try
		{
			$widgetNames	= $this->GetObjectNames_("widget");
			if (isset($widgetNames) && count($widgetNames) > 0)
			{
				foreach ($widgetNames as $widgetName)
				{
					$filename = WIDGET_PATH."KYR.Widgets.".$widgetName["widget"].".php";
					if (file_exists($filename))
						require_once WIDGET_PATH."KYR.Widgets.".$widgetName["widget"].".php";
					else
						throw new Exception("Widget not found");

					$widget = new $widgetName["widget"]($this->request);
					$widgets[$widgetName["widget"]] = $widget;
				}
			}
			else
				$widgets = null;
		}
		catch (Exception $ex) { throw $ex; }
		return $widgets;
	}

	/**
	 * Gets the list of objects names.
	 *
	 * @access	protected
	 * @param	string	$type	Type of object to get names.
	 * @return	array			Returns the list of object names.
	 *
	 */
	protected function GetObjectNames_($type)
	{
		$names	= array();
		$db		= null;
		$qry	= null;
		try
		{
			$db = new Database("MySQL");
			$qry = "CALL cms_Get".ucwords(strtolower($type))."Names(";
			$qry .= $this->request->pageID;
			$qry .= ")";
			$db->Query($qry);

			while ($name = $db->Fetch())
				$names[] = $name;
		}
		catch (DatabaseException $ex)
		{
			$ex->query = $qry;
			throw $ex;
		}
		return $names;
	}
	
	/**
	 * Loads layouts corresponding to the page.
	 *
	 * @access	private
	 * @param	array	$modules	List of modules.
	 * @param	array	$widgets	List of widgets.
	 *
	 */
	private function _LoadLayout($modules, $widgets)
	{
		//	Gets the title of the page.
		$pageTitle = $this->request->title;

		//	Gets the statusCode from modules.
		$statusCode	= null;
		foreach ($modules as $module)
		{
			$statusCode = $module->statusCode;
			if ($statusCode != 200)
				break;
		}

		//	Gets the layout file for the page.
		$db		= null;
		$qry	= null;
		$layout	= null;
		if ($statusCode == 200)
		{
			try
			{
				$db = new Database("MySQL");
				$qry = "CALL cms_GetPageLayout(";
				$qry .= $this->request->pageID;
				$qry .= ")";
				$db->Query($qry);

				$layout = $db->Fetch();
			}
			catch (DatabaseException $ex)
			{
				$ex->query = $qry;
				throw $ex;
			}
		}
		else
			$layout = array(
				"theme"		=> "default",
				"layout"	=> "one-column"
				);

		//	Gets the meta data for the page.
		$pageMeta	= null;
		try { $pageMeta = $this->_LoadPageMeta($statusCode); } catch (Exception $ex) { throw $ex; }

		//	Gets the CSS files for the page.
		$pageCSSes	= null;
		try { $pageCSSes = $this->_LoadPageCSSes($layout, $statusCode); } catch (Exception $ex) { throw $ex; }

		//	Gets the javascript files for the page.
		$pageJSes	= null;
		try { $pageJSes = $this->_LoadPageJSes($layout, $statusCode); } catch (Exception $ex) { throw $ex; }

		//	Imports the master theme file.
		require_once RESOURCE_PATH."template/master.php";
	}
	
	/**
	 * Loads metadata for the page.
	 *
	 * @access	private
	 * @param	string	$statusCode	Page status code.
	 * @return	string				Returns the metadata for the page.
	 *
	 */
	private function _LoadPageMeta($statusCode = 200)
	{
		$pageMeta	= null;
		$qry		= null;
		if ($statusCode == 200)
		{
			try
			{
				$db = new Database("MySQL");
				$qry = "CALL cms_GetPageMeta(";
				$qry .= $this->request->pageID;
				$qry .= ")";
				$db->Query($qry);

				while ($meta = $db->Fetch())
					$pageMeta .= "\t<meta name=\"".$meta["metaKey"]."\" content=\"".$meta["metaData"]."\" />\n";
			}
			catch (DatabaseException $ex)
			{
				$ex->query = $qry;
				throw $ex;
			}
		}
		else
		{
			$pageMeta .= "\t<meta name=\"Keywords\" content=\"\" />\n";
			$pageMeta .= "\t<meta name=\"Description\" content=\"\" />\n";
		}
		return $pageMeta;
	}
	
	/**
	 * Loads the list of CSSes.
	 *
	 * @access	private
	 * @param	array	$layout		Layout details.
	 * @param	string	$statusCode Page status code.
	 * @return	string				Returns the list of CSSes for the page.
	 *
	 */
	private function _LoadPageCSSes($layout, $statusCode = 200)
	{
		$pageCSSes	= null;
		$qry		= null;
		if ($statusCode == 200)
		{
			//	Gets the CSS file for the page from DB, if no error occurs.
			try
			{
				$db = new Database("MySQL");
				$qry = "CALL cms_GetPageCSSes(";
				$qry .= $this->request->pageID;
				$qry .= ")";
				$db->Query($qry);

				while ($css = $db->Fetch())
					$pageCSSes .= "\t<link type=\"text/css\" rel=\"stylesheet\" media=\"".$css["media"]."\" href=\"".BASE_URL."resources/css/".$css["href"].".css\" />\n";
			}
			catch (DatabaseException $ex)
			{
				$ex->query = $qry;
				throw $ex;
			}
		}
		else
		{
			//	Appends the CSS file for the page, if an error occurs.
			$pageCSSes .= "\t<link type=\"text/css\" rel=\"stylesheet\" media=\"screen\" href=\"".BASE_URL."resources/css/main.css\" />\n";
		}
		//	Appends the CSS file from the given layout.
		if (isset($layout))
			$pageCSSes .= "\t<link type=\"text/css\" rel=\"stylesheet\" media=\"screen\" href=\"".BASE_URL."resources/theme/".$layout["theme"]."/css/".$layout["theme"].".css\" />\n";

		return $pageCSSes;
	}
	
	/**
	 * Loads the list of javascripts.
	 *
	 * @access	private
	 * @param	array	$layout		Layout details.
	 * @param	string	$statusCode Page status code.
	 * @return	string				Returns the list of javascripts for the page.
	 *
	 */
	private function _LoadPageJSes($layout, $statusCode = 200)
	{
		$pageJSes	= null;
		$qry		= null;
		if ($statusCode == 200)
		{
			//	Gets the javascript file for the page from DB, if no error occurs.
			try
			{
				$db = new Database("MySQL");
				$qry = "CALL cms_GetPageJSes(";
				$qry .= $this->request->pageID;
				$qry .= ")";
				$db->Query($qry);

				while ($js = $db->Fetch())
					$pageJSes .= "\t<script type=\"text/javascript\" language=\"javascript\" src=\"".BASE_URL."resources/js/".$js["src"].".js\"></script>\n";
			}
			catch (DatabaseException $ex)
			{
				$ex->query = $qry;
				throw $ex;
			}
		}
		else
		{
			//	Appends the javascript file for the page, if an error occurs.
			$pageJSes .= "\t<script type=\"text/javascript\" language=\"javascript\" src=\"".BASE_URL."resources/js/main.js\"></script>\n";
		}
		//	Appends the javascript file from the given layout.
		if (isset($layout))
			$pageJSes .= "\t<script type=\"text/javascript\" language=\"javascript\" src=\"".BASE_URL."resources/theme/".$layout["theme"]."/js/".$layout["theme"].".js\"></script>\n";

		return $pageJSes;
	}
}
?>
